home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / transpor / ifmail23.z / ifmail23 / ifmail / ifcico / openport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  12.8 KB  |  687 lines

  1. #include <sys/types.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #ifdef HAS_IOCTL_H
  6. #include <sys/ioctl.h>
  7. #endif
  8. #include <fcntl.h>
  9. #include <string.h>
  10. #include <signal.h>
  11. #ifdef DONT_HAVE_PID_T
  12. #define pid_t int
  13. #endif
  14. #if defined(HAS_TERMIOS_H)
  15. #include <termios.h>
  16. #elif defined(HAS_TERMIO_H)
  17. #include <termio.h>
  18. #define speed_t int
  19. #elif defined(HAS_SGTTY_H)
  20. #include <bsd/sgtty.h>
  21. #error sgtty terminal control unimplemented yet
  22. #else
  23. #error must have termios.h, termio.h or sgtty.h
  24. #endif
  25. #include "lutil.h"
  26. #include "xutil.h"
  27. #include "ulock.h"
  28. #include "ttyio.h"
  29. #ifdef HAS_DIAL
  30. #ifdef HAS_DIAL_H
  31. #include <dial.h>
  32. #else
  33.  
  34. typedef struct {
  35.     void *attr;    /* struct termio may be undefined */
  36.     int baud;    /* unused */
  37.     int speed;    /* 212A modem: low=300, high=1200 */
  38.     char *line;    /* device name for out-going line */
  39.     char *telno;    /* ptr to tel-no/system name string */
  40.     int modem;    /* unused */
  41.     char *device;    /* pointer to a CALL_EXT structure */
  42.             /* this was unused previously */
  43.     int dev_len;    /* unused */
  44. } CALL;
  45.  
  46. extern int dial();
  47. extern void undial();
  48.  
  49. #endif /* HAS_DIAL_H */
  50.  
  51. static void dialerr();
  52.  
  53. #endif /* HAS_DIAL */
  54.  
  55. static char *openedport=NULL,*pname;
  56. static int need_detach=1;
  57.  
  58. extern int f_flags;
  59.  
  60. int openport(char*,int);
  61. void localport(void);
  62. void nolocalport(void);
  63. void closeport(void);
  64. int tty_raw(int);
  65. int tty_local(void);
  66. int tty_nolocal(void);
  67. int tty_cooked(void);
  68. void linedrop(int);
  69. void interrupt(int);
  70.  
  71. #if defined(HAS_TERMIO_H) || defined(HAS_TERMIOS_H)
  72. static speed_t transpeed(int);
  73. #endif
  74.  
  75. int hanged_up;
  76.  
  77. void linedrop(sig)
  78. int sig;
  79. {
  80.     loginf("got SIGHUP");
  81.     hanged_up=1;
  82.     return;
  83. }
  84.  
  85. void interrupt(sig)
  86. int sig;
  87. {
  88.     loginf("got SIGINT");
  89.     signal(SIGINT,interrupt);
  90.     return;
  91. }
  92.  
  93. int openport(port,speed)
  94. char *port;
  95. int speed;
  96. {
  97.     int rc;
  98.     char *errtty=NULL;
  99.     int fd;
  100.     int outflags;
  101. #ifdef HAS_DIAL
  102. #ifdef CS_PROB
  103.     CALL_EXT callx;
  104.     char protocols[64];
  105. #endif
  106.     CALL call;
  107.  
  108.     memset(&call,0,sizeof(call));
  109. #ifdef CS_PROB
  110.     memset(&callx,0,sizeof(callx));
  111.     callx.service="ifcico";
  112.     callx.protocol=protocols;
  113.     call.device=(char*)&callx;
  114. #endif
  115.     call.attr=0;
  116.     call.baud=-1;
  117.     call.telno=NULL;
  118. #endif
  119.  
  120.     debug(18,"try opening port \"%s\" at %d",port,speed);
  121.     if (openedport) free(openedport);
  122.     if (port[0] == '/') openedport=xstrcpy(port);
  123.     else
  124.     {
  125.         openedport=xstrcpy("/dev/");
  126.         openedport=xstrcat(openedport,port);
  127.     }
  128.     pname=strrchr(openedport,'/');
  129.  
  130. #ifndef HAS_DIAL
  131.     if ((rc=lock(pname)))
  132.     {
  133.         free(openedport);
  134.         openedport=NULL;
  135.         return rc;
  136.     }
  137. #endif
  138.  
  139.     if (need_detach)
  140.     {
  141.         fflush(stdin);
  142.         fflush(stdout);
  143.         setbuf(stdin,NULL);
  144.         setbuf(stdout,NULL);
  145.         close(0);
  146.         close(1);
  147.         if ((errtty=ttyname(2)))
  148.         {
  149.             debug(18,"stderr was on \"%s\", closing",errtty);
  150.             fflush(stderr);
  151.             close(2);
  152.         }
  153. #ifdef HAS_SETSID
  154.         if (setsid() < 0)
  155.         {
  156.             logerr("$setsid failed");
  157.             return 1;
  158.         }
  159. #else
  160. #ifdef BSD_SETPGRP
  161.         if (setpgrp(0,0) < 0)
  162. #else
  163.         if (setpgrp() < 0)
  164. #endif
  165.         {
  166.             logerr("$setpgrp failed");
  167.             return 1;
  168.         }
  169. #endif
  170.     }
  171.     tty_status=0;
  172.     hanged_up=0;
  173.     signal(SIGHUP,linedrop);
  174.     signal(SIGPIPE,linedrop);
  175.     signal(SIGINT,interrupt);
  176.     rc = 0;
  177.     debug(18,"try open");
  178. #ifdef HAS_DIAL
  179.     call.line=openedport;
  180.     if ((fd=dial(call)) < 0)
  181.     {
  182.         rc=1;
  183.         dialerr(fd);
  184.         fd=open("/dev/null",O_RDONLY);
  185.     }
  186.     else if (fd > 0)
  187.         if (dup(fd) != 0)
  188.         {
  189.             logerr("cannot dup fd %d to 0 (fd 0 busy?)",fd);
  190.             rc=1;
  191.         }
  192.         else
  193.         {
  194.             close(fd);
  195.             fd=0;
  196.         }
  197.     if (dup(fd) != 1)
  198.     {
  199.         rc=1;
  200.         logerr("$cannot dup stdin to stdout");
  201.         fd=open("/dev/null",O_WRONLY);
  202.     }
  203. #else
  204.     if ((fd=open(openedport,O_RDONLY|O_NONBLOCK)) != 0)
  205.     {
  206.         rc=1;
  207.         loginf("$cannot open \"%s\" as stdin",openedport);
  208.         fd=open("/dev/null",O_RDONLY);
  209.     }
  210.     if ((fd=open(openedport,O_WRONLY|O_NONBLOCK)) != 1)
  211.     {
  212.         rc=1;
  213.         loginf("$cannot open \"%s\" as stdout",openedport);
  214.         fd=open("/dev/null",O_WRONLY);
  215.     }
  216. #endif
  217.     clearerr(stdin);
  218.     clearerr(stdout);
  219.     if (need_detach)
  220.     {
  221. #ifdef TIOCSCTTY
  222.         if (ioctl(0,TIOCSCTTY,1L) < 0)
  223.         {
  224.             logerr("$TIOCSCTTY failed");
  225.             rc=1;
  226.         }
  227. #endif
  228.         if (errtty)
  229.         {
  230.             rc = rc || (open(errtty,O_WRONLY) != 2);
  231.         }
  232.         need_detach=0;
  233.     }
  234.     debug(18,"after open rc=%d",rc);
  235.     if (rc) loginf("cannot switch i/o to port \"%s\"",openedport);
  236.     else
  237.     {
  238.         if (tty_raw(speed))
  239.         {
  240.             logerr("$cannot set raw mode for \"%s\"",openedport);
  241.             rc=1;
  242.         }
  243.  
  244.         if (((f_flags=fcntl(0,F_GETFL,0L)) == -1) ||
  245.             ((outflags=fcntl(1,F_GETFL,0L)) == -1))
  246.         {
  247.             rc=1;
  248.             logerr("$GETFL error");
  249.             f_flags=0;
  250.             outflags=0;
  251.         }
  252.         else
  253.         {
  254.             debug(18,"return to blocking mode");
  255.             f_flags &= ~O_NONBLOCK;
  256.             outflags &= ~O_NONBLOCK;
  257.             if ((fcntl(0,F_SETFL,f_flags) != 0) ||
  258.                 (fcntl(1,F_SETFL,outflags) != 0))
  259.             {
  260.                 rc=1;
  261.                 logerr("$SETFL error");
  262.             }
  263.         }
  264.         debug(18,"file flags: stdin: 0x%04x, stdout: 0x%04x",
  265.             f_flags,outflags);
  266.     }
  267.  
  268.     if (rc) closeport();
  269.     return rc;
  270. }
  271.  
  272. void localport(void)
  273. {
  274.     debug(18,"setting port \"%s\" local",openedport);
  275.     signal(SIGHUP,SIG_IGN);
  276.     signal(SIGPIPE,SIG_IGN);
  277.     if (isatty(0)) tty_local();
  278.     return;
  279. }
  280.  
  281. void nolocalport(void)
  282. {
  283.     debug(18,"setting port \"%s\" non-local",openedport);
  284.     if (isatty(0)) tty_nolocal();
  285.     return;
  286. }
  287.  
  288. int rawport(void)
  289. {
  290.     tty_status=0;
  291.     signal(SIGHUP,linedrop);
  292.     signal(SIGPIPE,linedrop);
  293.     if (isatty(0)) return tty_raw(0);
  294.     else return 0;
  295. }
  296.  
  297. int cookedport(void)
  298. {
  299.     signal(SIGHUP,SIG_IGN);
  300.     signal(SIGPIPE,SIG_IGN);
  301.     if (isatty(0)) return tty_cooked();
  302.     else return 0;
  303. }
  304.  
  305. void closeport(void)
  306. {
  307.     debug(18,"closing port \"%s\"",openedport);
  308.     fflush(stdin);
  309.     fflush(stdout);
  310.     tty_cooked();
  311. #ifdef HAS_DIAL
  312.     close(1);
  313.     undial(0);
  314. #else
  315.     close(0);
  316.     close(1);
  317.     ulock(pname);
  318. #endif
  319.     if (openedport) free(openedport);
  320.     openedport=NULL;
  321.     return;
  322. }
  323.  
  324. void sendbrk(void)
  325. {
  326.     if (isatty(0))
  327. #if (defined(TIOCSBRK))
  328.     ioctl(0, TIOCSBRK, 0L);
  329. #elif (defined(TCSBRK))
  330.     ioctl(0, TCSBRK, 0L);
  331. #else /* any ideas about BSD? */
  332.     ;
  333. #endif
  334. }
  335.  
  336. #if defined(HAS_TERMIO_H)
  337.  
  338. static struct termio savetio;
  339. static struct termio tio;
  340.  
  341. int tty_raw(speed)
  342. int speed;
  343. {
  344.     int rc;
  345.     speed_t tspeed;
  346.  
  347.     debug(18,"set tty raw");
  348.     tspeed=transpeed(speed);
  349.     if ((rc=ioctl(0,TCGETA,&savetio)) != 0)
  350.     {
  351.         logerr("$ioctl(TCGETA) return %d",rc);
  352.         return rc;
  353.     }
  354.     else
  355.     {
  356.         debug(18,"savetio.c_iflag=0x%08x",savetio.c_iflag);
  357.         debug(18,"savetio.c_oflag=0x%08x",savetio.c_oflag);
  358.         debug(18,"savetio.c_cflag=0x%08x",savetio.c_cflag);
  359.         debug(18,"savetio.c_lflag=0x%08x",savetio.c_lflag);
  360.         debug(18,"savetio.c_cc=\"%s\"",printable(savetio.c_cc,NCC));
  361.         debug(18,"file flags: stdin: 0x%04x, stdout: 0x%04x",
  362.             fcntl(0,F_GETFL,0L),fcntl(1,F_GETFL,0L));
  363.     }
  364.     tio=savetio;
  365.     tio.c_iflag=0;
  366.     tio.c_oflag=0;
  367.     tio.c_cflag &= ~(CSTOPB | PARENB | PARODD);
  368.     tio.c_cflag |= CS8 | CREAD | HUPCL | CLOCAL;
  369.     if (tspeed)
  370.     {
  371.         tio.c_cflag &= ~CBAUD;
  372.         tio.c_cflag |= tspeed;
  373.     }
  374.     tio.c_lflag=0;
  375.     tio.c_cc[VMIN]=1;
  376.     tio.c_cc[VTIME]=0;
  377.     if ((rc=ioctl(0,TCSETAW,&tio)))
  378.         logerr("$ioctl(0,TCSETAW,raw) return %d",rc);
  379.     return rc;
  380. }
  381.  
  382. int tty_local(void)
  383. {
  384.     struct termio tio;
  385.     long cflag;
  386.     int rc;
  387.  
  388.     if ((rc=ioctl(0,TCGETA,&tio)))
  389.     {
  390.         logerr("$ioctl(TCGETA,save) return %d",rc);
  391.         return rc;
  392.     }
  393.     cflag=tio.c_cflag | CLOCAL;
  394.  
  395.     tio.c_cflag &= ~CBAUD;
  396.     if ((rc=ioctl(0,TCSETAW,&tio)))
  397.         logerr("$ioctl(0,TCSETAW,hangup) return %d",rc);
  398.  
  399.     sleep(1); /* as far as I notice, DTR goes back high on next op. */
  400.  
  401.     tio.c_cflag=cflag;
  402.     if ((rc=ioctl(0,TCSETAW,&tio)))
  403.         logerr("$ioctl(0,TCSETAW,clocal) return %d",rc);
  404.     return rc;
  405. }
  406.  
  407. int tty_nolocal(void)
  408. {
  409.     struct termio tio;
  410.     int rc;
  411.  
  412.     if ((rc=ioctl(0,TCGETA,&tio)))
  413.     {
  414.         logerr("$ioctl(TCGETA,save) return %d",rc);
  415.         return rc;
  416.     }
  417.     tio.c_cflag &= ~CLOCAL;
  418. #if defined(CRTSCTS)
  419.     tio.c_cflag |= CRTSCTS;
  420. #elif defined(CRTSFL)
  421.     tio.c_cflag |= CRTSFL;
  422. #else /* donno what can be done here... Protocols won't run w/o hw flow ctl. */
  423.     tio.c_cflag |= 0;
  424. #endif
  425.  
  426.     if ((rc=ioctl(0,TCSETAW,&tio)))
  427.         logerr("$ioctl(0,TCSETAW,clocal) return %d",rc);
  428.     return rc;
  429. }
  430.  
  431. int tty_cooked(void)
  432. {
  433.     int rc;
  434.  
  435.     if ((rc=ioctl(0,TCSETAF,&savetio)) != 0)
  436.         logerr("$ioctl(TCSETAF) return %d",rc);
  437.     return rc;
  438. }
  439.  
  440. #elif defined(HAS_TERMIOS_H)
  441.  
  442. static struct termios savetios;
  443. static struct termios tios;
  444.  
  445. int tty_raw(speed)
  446. int speed;
  447. {
  448.     int rc;
  449.     speed_t tspeed;
  450.  
  451.     debug(18,"set tty raw");
  452.     tspeed=transpeed(speed);
  453.     if ((rc=tcgetattr(0,&savetios)))
  454.     {
  455.         logerr("$tcgetattr(0,save) return %d",rc);
  456.         return rc;
  457.     }
  458.     else
  459.     {
  460.         debug(18,"savetios.c_iflag=0x%08x",savetios.c_iflag);
  461.         debug(18,"savetios.c_oflag=0x%08x",savetios.c_oflag);
  462.         debug(18,"savetios.c_cflag=0x%08x",savetios.c_cflag);
  463.         debug(18,"savetios.c_lflag=0x%08x",savetios.c_lflag);
  464.         debug(18,"savetios.c_cc=\"%s\"",printable(savetios.c_cc,NCCS));
  465.         debug(18,"file flags: stdin: 0x%04x, stdout: 0x%04x",
  466.             fcntl(0,F_GETFL,0L),fcntl(1,F_GETFL,0L));
  467.     }
  468.     tios=savetios;
  469.     tios.c_iflag=0;
  470.     tios.c_oflag=0;
  471.     tios.c_cflag &= ~(CSTOPB | PARENB | PARODD);
  472.     tios.c_cflag |= CS8 | CREAD | HUPCL | CLOCAL;
  473.     tios.c_lflag=0;
  474.     tios.c_cc[VMIN]=1;
  475.     tios.c_cc[VTIME]=0;
  476.     if (tspeed)
  477.     {
  478.         cfsetispeed(&tios,tspeed);
  479.         cfsetospeed(&tios,tspeed);
  480.     }
  481.     if ((rc=tcsetattr(0,TCSADRAIN,&tios)))
  482.         logerr("$tcsetattr(0,TCSADRAIN,raw) return %d",rc);
  483.     return rc;
  484. }
  485.  
  486. int tty_local(void)
  487. {
  488.     struct termios tios;
  489.     tcflag_t cflag;
  490.     speed_t ispeed,ospeed;
  491.     int rc;
  492.  
  493.     if ((rc=tcgetattr(0,&tios)))
  494.     {
  495.         logerr("$tcgetattr(0,save) return %d",rc);
  496.         return rc;
  497.     }
  498.     cflag=tios.c_cflag | CLOCAL;
  499.  
  500.     ispeed=cfgetispeed(&tios);
  501.     ospeed=cfgetospeed(&tios);
  502.     cfsetispeed(&tios,0);
  503.     cfsetospeed(&tios,0);
  504.     if ((rc=tcsetattr(0,TCSADRAIN,&tios)))
  505.         logerr("$tcsetattr(0,TCSADRAIN,hangup) return %d",rc);
  506.  
  507.     sleep(1); /* as far as I notice, DTR goes back high on next op. */
  508.  
  509.     tios.c_cflag=cflag;
  510.     cfsetispeed(&tios,ispeed);
  511.     cfsetospeed(&tios,ospeed);
  512.     if ((rc=tcsetattr(0,TCSADRAIN,&tios)))
  513.         logerr("$tcsetattr(0,TCSADRAIN,clocal) return %d",rc);
  514.     return rc;
  515. }
  516.  
  517. int tty_nolocal(void)
  518. {
  519.     struct termios tios;
  520.     int rc;
  521.  
  522.     if ((rc=tcgetattr(0,&tios)))
  523.     {
  524.         logerr("$tcgetattr(0,save) return %d",rc);
  525.         return rc;
  526.     }
  527.     tios.c_cflag &= ~CLOCAL;
  528. #if defined(CRTSCTS)
  529.     tios.c_cflag |= CRTSCTS;
  530. #elif defined(CRTSFL)
  531.     tios.c_cflag |= CRTSFL;
  532. #else /* donno what can be done here... Protocols won't run w/o hw flow ctl. */
  533.     tios.c_cflag |= 0;
  534. #endif
  535.  
  536.     if ((rc=tcsetattr(0,TCSADRAIN,&tios)))
  537.         logerr("$tcsetattr(0,TCSADRAIN,clocal) return %d",rc);
  538.     return rc;
  539. }
  540.  
  541. int tty_cooked(void)
  542. {
  543.     int rc;
  544.  
  545.     if ((rc=tcsetattr(0,TCSAFLUSH,&savetios)))
  546.         logerr("$tcsetattr(0,TCSAFLUSH,save) return %d",rc);
  547.     return rc;
  548. }
  549.  
  550. #elif defined(HAS_SGTTY_H)
  551.  
  552. /* Never used BSD style terminal control, did you? */
  553.  
  554. static struct sgtty savetty;
  555.  
  556. int tty_raw(speed)
  557. int speed;
  558. {
  559.     debug(18,"set tty raw");
  560.     if (ioctl(0,TIOCGETP,&savetty) != 0) return 1);
  561. }
  562.  
  563. int tty_cooked(void)
  564. {
  565.     return tcsetattr(0,TIOCSETN,&savetty);
  566. }
  567.  
  568. int tty_local(void)
  569. {
  570.     return 0;
  571. }
  572.  
  573. int tty_nolocal(void)
  574. {
  575.     return 0;
  576. }
  577.  
  578. #endif /* types of terminal control */
  579.  
  580. #ifdef HAS_DIAL
  581.  
  582. static void dialerr(fd)
  583. int fd;
  584. {
  585.     char *em;
  586.  
  587.     switch (fd)
  588.     {
  589.     case INTRPT:    em="interrupt occured"; break;
  590.     case D_HUNG:    em="dialer hung (no return from write)"; break;
  591.     case NO_ANS:    em="no answer within 10 seconds"; break;
  592.     case ILL_BD:    em="illegal baud rate"; break;
  593.     case A_PROB:    em="acu problem (open() failure)"; break;
  594.     case L_PROB:    em="line problem (open() failure)"; break;
  595.     case NO_Ldv:    em="can't open LDEVS file"; break;
  596.     case DV_NT_A:    em="requested device not available"; break;
  597.     case DV_NT_K:    em="requested device not known"; break;
  598.     case NO_BD_A:    em="no device available at requestd baud"; break;
  599.     case NO_BD_K:    em="no device known at requestd baud"; break;
  600.     case DV_NT_E:    em="requested speed doesn't match"; break;
  601.     case BAD_SYS:    em="system not in System file"; break;
  602. #ifdef CS_PROB
  603.     case CS_PROB:    em="communication server problem"; break;
  604. #endif
  605.     
  606.     default:    em="unknown error code"; break;
  607.     }
  608.     loginf("dial error\n\tfd=%d : %s",fd,em);
  609. }
  610.  
  611. #endif
  612.  
  613. #if defined(HAS_TERMIO_H) || defined(HAS_TERMIOS_H)
  614. speed_t transpeed(speed)
  615. int speed;
  616. {
  617.     speed_t tspeed;
  618.  
  619.     switch (speed)
  620.     {
  621.     case 0:        tspeed=0; break;
  622. #if defined(B50)
  623.     case 50:    tspeed=B50; break;
  624. #endif
  625. #if defined(B75)
  626.     case 75:    tspeed=B75; break;
  627. #endif
  628. #if defined(B110)
  629.     case 110:    tspeed=B110; break;
  630. #endif
  631. #if defined(B134)
  632.     case 134:    tspeed=B134; break;
  633. #endif
  634. #if defined(B150)
  635.     case 150:    tspeed=B150; break;
  636. #endif
  637. #if defined(B200)
  638.     case 200:    tspeed=B200; break;
  639. #endif
  640. #if defined(B300)
  641.     case 300:    tspeed=B300; break;
  642. #endif
  643. #if defined(B600)
  644.     case 600:    tspeed=B600; break;
  645. #endif
  646. #if defined(B1200)
  647.     case 1200:    tspeed=B1200; break;
  648. #endif
  649. #if defined(B1800)
  650.     case 1800:    tspeed=B1800; break;
  651. #endif
  652. #if defined(B2400)
  653.     case 2400:    tspeed=B2400; break;
  654. #endif
  655. #if defined(B4800)
  656.     case 4800:    tspeed=B4800; break;
  657. #endif
  658. #if defined(B7200)
  659.     case 7200:    tspeed=B7200; break;
  660. #endif
  661. #if defined(B9600)
  662.     case 9600:    tspeed=B9600; break;
  663. #endif
  664. #if defined(B12000)
  665.     case 12000:    tspeed=B12000; break;
  666. #endif
  667. #if defined(B14400)
  668.     case 14400:    tspeed=B14400; break;
  669. #endif
  670. #if defined(B19200)
  671.     case 19200:    tspeed=B19200; break;
  672. #elif defined(EXTA)
  673.     case 19200:    tspeed=EXTA; break;
  674. #endif
  675. #if defined(B38400)
  676.     case 38400:    tspeed=B38400; break;
  677. #elif defined(EXTB)
  678.     case 38400:    tspeed=EXTB; break;
  679. #endif
  680.     default:    logerr("requested invalid speed %d",speed);
  681.             tspeed=0; break;
  682.     }
  683.  
  684.     return tspeed;
  685. }
  686. #endif
  687.